package escalonador;

/**
 * Classe responsavel por executar os processos.
 * 
 * @author Barbara Barbosa Silva
 * @author Daniel Tsuha
 * @author Felipe Sa de Mello
 * @author Lucas Machado
 */
public class Processador {

	/**
	 * Variavel responsavel por armazenar o Quantum.
	 */
	int quantum;

	/**
	 * Variavel responsavel por guardar o valor do registrador X.
	 */
	int X;

	/**
	 * Variavel responsavel por guardar o valor do registrador Y.
	 */
	int Y;

	/**
	 * Variavel responsavel por guardar o valor do Contador de Programa.
	 */
	int PC;

	/**
	 * Construtor da classe processador.
	 * 
	 * @param quantum
	 *            Quantidade de quanta a ser usada para cada processo.
	 */
	public Processador(int quantum) {
		this.quantum = quantum;
	}

	/**
	 * Metodo que carrega do BCP os valores dos registradores para a execucao.
	 * 
	 * @param processo
	 *            {@link BCP} do programa que sera processado.
	 */
	void carregaRegistradoresDoProcesso(BCP processo) {
		this.X = processo.X;
		this.Y = processo.Y;
		this.PC = processo.PC;
		processo.vezesProcessado++;
	}

	/**
	 * Metodo que grava no BCP os valores dos registradores.
	 * 
	 * @param processo
	 *            {@link BCP} do processo em que deve ser salvos os valores dos
	 *            registradores.
	 */
	void gravaRegistradoresDoProcesso(BCP processo) {
		processo.X = this.X;
		processo.Y = this.Y;
		processo.PC = this.PC;
	}

	/**
	 * Processa os dados do BCP. Representa o nucleo do processador.
	 * 
	 * @param processo
	 *            {@link BCP} do processo a ser executado.
	 * @return {@link Util.statusProcesso} estado do processo.
	 */
	public Util.statusProcesso processaBCP(BCP processo) {
		this.carregaRegistradoresDoProcesso(processo);
		int i;
		for (i = 0; i < this.quantum; i++) {
			String comando;
			if (this.PC == processo.comandos.size()) {
				comando = null;
			} else {
				comando = processo.comandos.get(PC);
			}
			this.PC++;

			if (comando == null || comando.length() == 0) {
				return Util.statusProcesso.TERMINADO;

				// } else if(comando.equals("COM")) {
				// Logger.executando(processo);

			} else if (comando.equals("E/S")) {
				Logger.entradaSaida(processo);
				Logger.interrompendo(processo, i);
				processo.latencia += 2;
				this.gravaRegistradoresDoProcesso(processo);
				RoundRobin.instrucoes += i;
				return Util.statusProcesso.BLOQUEADO;

			} else if (comando.charAt(0) == 'X') {
				this.X = Integer.parseInt(comando.substring(comando.indexOf("=")+1));

			} else if (comando.charAt(0) == 'Y') {
				this.Y = Integer.parseInt(comando.substring(comando.indexOf("=")+1));
			}
		}
		Logger.interrompendo(processo, i);
		this.gravaRegistradoresDoProcesso(processo);
		RoundRobin.instrucoes += i;
		return Util.statusProcesso.PRONTO;
	}
}